<?php

namespace app\admin\service\exif;

use app\admin\service\BaseService;
use app\common\model\user\User;
use app\common\utils\FileUtil;
use app\common\utils\MyTools;
use Overtrue\Pinyin\Pinyin;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Queue;

class ExifService extends BaseService
{
    /**
     * 根据图片或视频的Exif信息中的拍摄时间重命名文件
     * @param string $dir 文件路径
     * @return void
     */
    public static function renameFilesByExif(string $dir)
    {
        $file_list = FileUtil::readAllFiles($dir, false);
        foreach ($file_list as $file_path) {
            $filename = FileUtil::getFileNameByPath($file_path);
            $item_data = self::_getPrefixAndSuffix($filename);

            //判断后缀
            if (in_array($item_data['suffix'], ['JPG', 'JPEG', 'PNG'])) {
                $time_name = self::_getImageCreateDate($file_path, true);
                if (!$time_name) {
                    $time_name = self::_getVideoCreateDate($file_path);
                }
            } else if (in_array($item_data['suffix'], ['MP4', 'MOV', 'BMP', 'GIF', 'HEIC'])) {
                $time_name = self::_getVideoCreateDate($file_path);
            } else {
                //echo "unknow suffix, continue1... \n";
                continue;
            }

            if (!$time_name) {
                //echo "empty imgTime, continue2... \n";
                continue;
            }

            $new_name = $item_data['prefix'] . $time_name . '_' . $filename; //格式：20171006_160041_原来的名称.JPG,追加旧名称防止同一秒的多个文件被覆盖到一个
            $new_file_path = $dir . DIRECTORY_SEPARATOR . $new_name;
            //PE($file_path . '  --> ' . $new_file_path);

            //执行重命名
            rename($file_path, $new_file_path);
        }
    }

    /**
     * 对已经处理过的 20171006_160041_原来的名称.JPG 二次处理，最终文件名称:20171006_160041_1.JPG
     * @param string $dir 文件路径
     */
    public static function renameFilesAgain(string $dir)
    {
        //按照每一秒划分为二维数组
        $file_list = FileUtil::readAllFiles($dir);
        $file_data = [];
        foreach ($file_list as $file_path) {
            $filename = FileUtil::getFileNameByPath($file_path);
            $item_data = self::_getPrefixAndSuffix($filename);
            $tmp_filename_string = explode('_', $item_data['tmp_filename_string']);
            if (empty($tmp_filename_string[0]) || empty($tmp_filename_string[1])) {
                continue;
            }
            $key = $tmp_filename_string[0] . $tmp_filename_string[1];
            $file_data[$key][] = $filename;
        }

        //重新开始重命名
        $num = 1;
        foreach ($file_data as $item) {
            foreach ($item as $k => $v) {
                $data = self::_getPrefixAndSuffix($v);
                $name_arr = explode('_', $data['tmp_filename_string']);
                if (count($name_arr) < 3) {
                    continue;
                }

                if (count($item) == 1) { //同一秒只有一个文件
                    $append = '';
                } else { //同一秒有多个文件，需要给后面追加 _1/2/3 等等
                    $append = '_' . ($k + 1);
                }

                $new_name = $data['prefix'] . $name_arr[0] . '_' . $name_arr[1] . $append . '.' . $data['suffix'];
                echo '[' . $num . '] ' . $v . " --> " . $new_name . "\n";

                $old = $dir . DIRECTORY_SEPARATOR . $v;
                $new = $dir . DIRECTORY_SEPARATOR . $new_name;
                rename($old, $new);
                $num++;
            }
        }
    }

    /**
     * 修改图片或视频的拍摄时间
     * @return void
     */
    public static function setExifCreateDate($dir)
    {

    }

    /**
     * 对文件名称拆解,提取前缀和后缀
     * @param string $filename
     * @return array
     */
    private static function _getPrefixAndSuffix(string $filename): array
    {
        if (substr($filename, 0, 4) == 'IMG_') {
            $prefix = 'IMG_';
            $tmp_filename = substr($filename, 4);
        } elseif (substr($filename, 0, 11) == 'Screenshot_') {
            $prefix = 'IMG_';
            $tmp_filename = substr($filename, 11);
        } elseif (substr($filename, 0, 4) == 'VID_') {
            $prefix = 'VID_';
            $tmp_filename = substr($filename, 4);
        } else {
            $prefix = '';
            $tmp_filename = $filename;
        }

        $tmp_filename_array = explode('.', $tmp_filename);
        $tmp_filename_string = $tmp_filename_array[0];
        $suffix = strtoupper($tmp_filename_array[count($tmp_filename_array) - 1]);

        return [
            'prefix' => $prefix, //前缀
            'suffix' => $suffix, //后缀（大写）
            'tmp_filename' => $tmp_filename, //不包含前缀的完整名称
            'tmp_filename_string' => $tmp_filename_string, //不包含前缀和后缀的名称
        ];
    }

    /**
     * 获取图片的拍摄时间
     * @param $file_path string 文件路径
     * @param $useFileDateTime bool 是否使用文件在磁盘的写入时间:FileDateTime
     * @return string 返回格式：20170912_190328
     */
    private static function _getImageCreateDate(string $file_path, bool $useFileDateTime = false): ?string
    {
        $file_arr = @exif_read_data($file_path);
        $FileDateTime = strtotime(@$file_arr['DateTimeOriginal']); //时间戳
        if (!$FileDateTime) {
            $FileDateTime = strtotime(@$file_arr['DateTime']);
        }
        if ($FileDateTime) {
            return date("Ymd_His", $FileDateTime);
        }

        if ($useFileDateTime && !empty($file_arr['FileDateTime'])) {
            return date("Ymd_His", $file_arr['FileDateTime']);
        }

        return null;
    }

    /**
     * 获取视频的拍摄时间
     * @param $file_path string 文件路径
     * @return string 返回格式：20170912_190328
     */
    private static function _getVideoCreateDate(string $file_path): ?string
    {
        $cmd = 'exiftool ' . $file_path;
        exec($cmd, $file_arr);
        if (empty($file_arr)) {
            return false;
        }

        $file_data = [];
        foreach ($file_arr as $item) {
            $item = explode(':', $item);
            $key = trim(str_replace(' ', '', $item[0]));

            unset($item[0]);
            $value = trim(implode(':', $item));
            $file_data[$key] = $value;
        }
        $video_create_time = $file_data['CreationDate'];
        $video_create_timestamp = strtotime($video_create_time);
        if (!empty($video_create_timestamp)) {
            return date("Ymd_His", $video_create_timestamp);
        }

        $file_modify_data = $file_data['FileModificationDate/Time'];
        $file_modify_data_timestamp = strtotime($file_modify_data);
        if (!empty($file_modify_data_timestamp)) {
            return date("Ymd_His", $file_modify_data_timestamp);
        }

        return null;
    }

}